using System.Collections.Generic;
using cfg;
using cfg.ability;
using cfg.enemy;
using cfg.level;
using cfg.wave;
using SimpleJSON;
using UnityEngine;
using Random = UnityEngine.Random;

namespace QFramework.Monk
{
    public class ConfigModel : AbstractModel
    {
        public Tables configTables { get; private set; }
        private ResLoader mResLoader;
        protected override void OnInit()
        {
            mResLoader = ResLoader.Allocate();
            LoadConfig();
        }

        protected override void OnDeinit()
        {
            base.OnDeinit();
            mResLoader.Recycle2Cache();
            mResLoader = null;
        }

        private void LoadConfig() // 注意方法名的拼写错误
        {
            configTables = new cfg.Tables((file =>
            {
                var textAsset = mResLoader.LoadSync<TextAsset>(file);
                return JSON.Parse(textAsset.text);
            }));
        }

        #region Ability
        /// <summary>
        /// 升级能力
        /// </summary>
        /// <param name="curLevel"></param>
        /// <param name="abilityType"></param>
        public void UpAbility(int curLevel,AbilityType abilityType)
        {
            var nextAbilityConfig = GetNextAbilityByType(curLevel,abilityType);
            var abilityGroupConfig = GetAbilityGroupByType(abilityType);
            if (AppStart.goldNum.Value<nextAbilityConfig.Price)
            {
                return;
            }
            
            if (curLevel>=abilityGroupConfig.MaxLv)
            {
                return;
            }
            
            AppStart.goldNum.Value -= nextAbilityConfig.Price;
            PlayerPrefs.SetInt("goldNum", AppStart.goldNum.Value);
            switch (abilityType)
            {
                case  AbilityType.Exp :
                    AppStart.expDropLv.Value = curLevel+1;
                    AppStart.expDropPrecent.Value += nextAbilityConfig.Precent;
                    PlayerPrefs.SetInt("expDropLv", curLevel+1);
                    PlayerPrefs.SetFloat("expDropPrecent", AppStart.expDropPrecent.Value);
                    break;
                case AbilityType.MaxHp :
                    AppStart.hpLv.Value = curLevel+1;
                    AppStart.maxHp.Value += nextAbilityConfig.Value;
                    PlayerPrefs.SetInt("hpLv", curLevel+1);
                    PlayerPrefs.SetInt("maxHp", AppStart.maxHp.Value);
                    break;
                case  AbilityType.Coin :
                    AppStart.coinDropLv.Value = curLevel+1;
                    AppStart.coinDropPrecent.Value += nextAbilityConfig.Precent;
                    PlayerPrefs.SetInt("coinDropLv", curLevel+1);
                    PlayerPrefs.SetFloat("coinDropPrecent", AppStart.coinDropPrecent.Value);
                    break;
                case AbilityType.Attack :
                    AppStart.attackLv.Value = curLevel+1;
                    AppStart.damage.Value += nextAbilityConfig.Value;
                    PlayerPrefs.SetInt("attackLv", curLevel+1);
                    PlayerPrefs.SetFloat("damage", AppStart.damage.Value);
                    break;
            } 
        }

        /// <summary>
        /// 得到下一级能力config
        /// </summary>
        /// <param name="curLevel"></param>
        /// <param name="abilityType"></param>
        /// <returns></returns>
        public Ability GetNextAbilityByType(int curLevel,AbilityType abilityType)
        {
            var abilityGroupConfig = GetAbilityGroupByType(abilityType);
            var nextAbilityId = 0;
            if (curLevel>=abilityGroupConfig.MaxLv)
            {
                nextAbilityId = abilityGroupConfig.List[curLevel];
            }
            else
            {
                nextAbilityId = abilityGroupConfig.List[curLevel+1];
                
            }
            var nextAbilityConfig = configTables.TbAbility.Get(nextAbilityId);
            return nextAbilityConfig;
        }
        
        public AbilityGroup GetAbilityGroupByType(AbilityType abilityType)
        {
            return configTables.TbAbilityGroup.Get((int)abilityType);
        }
        #endregion
        #region Level

        public LevelUp GetLevelUpConfig(int level)
        {
            return configTables.TbLevelUp.Get(level);
        }

        public bool CheckCanLevelUp(int level)
        {
            return level<configTables.TbLevelUp.DataList.Count;
        }
        
        /// <summary>
        /// 获取对应类型的所有能力
        /// </summary>
        /// <param name="skillType"></param>
        /// <returns></returns>
        public SkillGroup GetAllSkillItemByType(SkillType skillType)
        {

          return  configTables.TbSkillGroup.Get(skillType);
        }
        
        public SkillItem GetSkillItemConfig(int level,SkillType skillType)
        {
            if (!CheckIsMaxSkillLv(level,skillType))
            {
                var skillGroupConfig = GetAllSkillItemByType(skillType);
                return skillGroupConfig.Y1[level];
                
            }
            return null;
        }
        
        /*/// <summary>
        /// 特殊能力需要根据能力解锁获取下个能力
        /// </summary>
        /// <param name="level"></param>
        /// <param name="skillType"></param>
        /// <returns></returns>
        public SkillItem GetNextSkillItem(int level, SkillType skillType)
        {
            var skillGroupConfig = GetAllSkillItemByType(skillType);
            var curSkillItemConfig = GetSkillItemConfig(level, skillType);
            foreach (var item in skillGroupConfig.Y1)
            {
                if (item.Value.Id==curSkillItemConfig.RefId)
                {
                    return  item.Value;
                }
            }
            return  null;
        }*/
        
        /// <summary>
        /// 能力是否满级
        /// </summary>
        /// <param name="level"></param>
        /// <param name="skillType"></param>
        /// <returns></returns>
        public bool CheckIsMaxSkillLv(int level,SkillType skillType)
        {
            var skillGroupConfig = GetAllSkillItemByType(skillType);
            return !skillGroupConfig.Y1.ContainsKey(level);
        }
        
        public void LevelUp(SkillItem skillItem)
        {
            switch (skillItem.SkillType)
            {
                case SkillType.Attack:
                    AppStart.attackSkillLv.Value += 1;
                    AppStart.damage.Value += skillItem.Value;
                    break;
                case SkillType.AttackCD:
                    AppStart.attackCdSkillLv.Value += 1;
                    AppStart.ackDuration.Value =
                        Mathf.Max(0.5f, AppStart.ackDuration.Value - 1.5f*((float)skillItem.Value / 100));
                    break;
                case SkillType.Speed:
                    AppStart.speedSkillLv.Value += 1;
                    AppStart.playerSpeed.Value += skillItem.Value;
                    break;
                case SkillType.Axe:
                    Player.Default.SimpleAxe.LevelUp(skillItem);
                    break;
                case SkillType.Sword:
                    Player.Default.SimpleSword.LevelUp(skillItem);
                    break;
                case SkillType.Knife:
                    Player.Default.SimpleKnife.LevelUp(skillItem);
                    break;
                case SkillType.Shield:
                    Player.Default.SimpleCircle.LevelUp(skillItem);
                    break;
                case  SkillType.Ball:
                    Player.Default.SimpleBall.LevelUp(skillItem);
                    break;
                
            }
        }
        
        #endregion
        #region Wave

        public EnemyInfo GetEnemyConfig(int id)
        {
            return configTables.TbEnemyInfo.Get(id);
        }
        
        public Wave GetWaveConfig(int id)
        {
            return configTables.TbWave.Get(id);
        }

        public List<Wave> GetAllWaveConfig()
        {
            return configTables.TbWave.DataList;
        }

        public EnemyInfo RandomCreateEnemy(Wave curWave)
        {
            var randomIndex = Random.Range(0, curWave.Enmeies.Count);
            var enemyId = curWave.Enmeies[randomIndex];
            return GetEnemyConfig(enemyId);
        }

        #endregion
    }
    
}

